package com.ruoyi.web.core.service;

import com.ruoyi.net.service.IElementAlarmService;
import com.ruoyi.net.service.IPerformanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class UdpDiscoveryService {

    private static final int PORT = 17889; // 监听的端口号
    private DatagramSocket socket;
    private ScheduledExecutorService executorService;

//    @PostConstruct
    public void init() throws Exception {
        socket = new DatagramSocket(PORT);
        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(this::listenForDevices, 0, 1, TimeUnit.SECONDS);
    }

    private void listenForDevices() {
        System.out.println("启动端口监听: " + PORT);
        try {
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            socket.receive(packet);
            // source ip
            InetAddress sourceAddress = packet.getAddress();
            String sourceIp = sourceAddress.getHostAddress();
            int sourcePort = packet.getPort();
            System.out.println("Received packet from: " + sourceIp + ":" + sourcePort);
            // 判断接收内容长度（主动上报）
            int limitedLength = 28;
            if (packet.getLength() > limitedLength) {
            /*
             TODO: 2024/11/7  这里可以添加处理逻辑，例如将设备信息存储到数据库或发送响应等
             解析
             截取
            */
                int length = packet.getLength() - limitedLength;
                byte[] subArray = new byte[length];
                System.arraycopy(packet, limitedLength, subArray, 0, length);
                // 是否告警开头
                byte a = subArray[0];
                // JC04
                if (subArray[0] == 74 && subArray[1] == 67 && subArray[2] == 4) {

                }
                // MS05、MS07
                else if (subArray[0] == 77 && subArray[1] == 83 && (subArray[2] == 5 || subArray[2] == 7)) {
                /*协议头，NE地址1，NE地址2，NE特征字1，NE特征字2，盘类型1，盘类型2，盘类型3，盘类型4，盘地址1，盘地址2，盘特征字1，盘特征字2，备用1，备用2，盘数据长度1，盘数据长度2，盘数据长度3，盘数据长度4，
                线路1，线路1，线路1数据长度1，线路1数据长度2，线路1数据长度3，线路1数据长度4，
                告警代码1，告警状态1，(告警发生时间)年，年，月，日，时，分，秒，……，告警代码m，告警状态m，(告警发生时间)年，年，月，日，时，分，秒，*/
                    // 网元地址-网块号
                    int byPartNo = subArray[22];
                    // 网元地址-网元号
                    int byNeNo = subArray[23];
                    // 网元特征字1
                    int neKeyBytes1 = subArray[24];
                    // 网元特征字2
                    int neKeyBytes2 = subArray[25];
                    // 盘总数【2字节】
                    int byBoardCount = subArray[26] * 10 + subArray[27];
                    // 盘类型【4字节】 28,29,30,31
                    // 盘地址1
                    int byGroupNo = subArray[32];
                    // 盘地址2
                    int byBoardAddress = subArray[33];
                    // 盘特征1
                    int boardKeyBytes1 = subArray[34];
                    // 盘特征2
                    int boardKeyBytes2 = subArray[35];
                    // 备用1，备用2 36,37
                    // 盘数据长度【4字节】 38,39,40,41
                    int dwAlarmDataLength = subArray[38] * 1000 + subArray[39] * 100 + subArray[40] * 10 + subArray[41];

                    if (dwAlarmDataLength > 0) {
                        // 线路号【2字节】42,43
                        // 线路数据长度[4字节] 44,45,46,47
                        int lineData = subArray[44] * 1000 + subArray[45] * 100 + subArray[46] * 10 + subArray[47];
                        for (int i=0; i<lineData/9; i++) {
                            int tmp = 47 + i * 9;
                            // 告警类型/代码
                            int alarmCode = subArray[tmp + 1]; // 0x43
                            // 告警状态1
                            int alarmStatus1 = subArray[tmp + 2]; // 0x13
                            // (状态变化时间)年
                            int year = subArray[tmp + 3];
                            // 年、月、日、时、分、秒
                            int year1 = subArray[tmp + 4];
                            int month = subArray[tmp + 5];
                            int day = subArray[tmp + 6];
                            int hour = subArray[tmp + 7];
                            int minute = subArray[tmp + 8];
                            int second = subArray[tmp + 9];
                            // 组装告警信息入库

                        }
                    }

                }
                // 是否性能 PS05
                else if (subArray[0] == 80 && subArray[1] == 83 && subArray[2] == 5) {
                /*协议头，性能数据类型,NE地址1，NE地址2，NE状态，备用，盘总数(高)，盘总数(低)，--28
                盘1类型1，盘1类型2，盘1类型3，盘1类型4，盘1地址1，盘1地址2，盘1状态，备用，盘1数据长度1，盘1数据长度2，盘1数据长度3，盘1数据长度4，--40
                性能数据块1长度1，性能数据块1长度2，性能数据块1长度3，性能数据块1长度4，
                线路号1，线路号1，线路1数据长度1，线路1数据长度2，线路1数据长度3，线路1数据长度4，
                性能代码1，性能(高)，性能(低)，……，性能代码n，性能(高)，性能(低)，*/
                    // 性能数据类型
                    int byDataType = subArray[22];
                    // 网元地址-网块号
                    int byPartNo = subArray[23];
                    // 网元地址-网元号
                    int byNeNo = subArray[24];
                    // NE状态
                    int byNeStatus = subArray[25];
                    // 备用 int byBak = subArray[26];
                    // 盘总数【2字节】
                    int byBoardCount = subArray[27] * 10 + subArray[28];
                    // 盘类型【4字节】 29,30,31,32
                    // 盘地址1
                    int byGroupNo = subArray[33];
                    // 盘地址2
                    int byBoardAddress = subArray[34];
                    // 盘状态
                    int byBoardStatus = subArray[35];
                    // 备用 int byBak1 = subArray[36];
                    // 盘数据长度【4字节】 37,38,39,40
                    int dwBoardDataLen = subArray[37] * 1000 + subArray[38] * 100 + subArray[39] * 10 + subArray[40];
                    // 性能块长度【4字节】41,42,43,44
                    int dwPerformanceDataLength = subArray[41] * 1000 + subArray[42] * 100 + subArray[43] * 10 + subArray[44];
                    if (dwPerformanceDataLength > 0) {
                        // 线路号【2字节】45,46
                        // 线路数据长度[4字节] 47,48,49,50
                        int lineData = subArray[47] * 1000 + subArray[48] * 100 + subArray[49] * 10 + subArray[50];
                        for (int i=0; i<lineData/3; i++) {
                            int tmp = 50 + i * 3;
//                        性能代码1，性能(高)，性能(低)
                            int performanceCode = subArray[tmp + 1];
                            int performanceData = subArray[tmp + 2] * 10 + subArray[tmp + 3];
                            // 组装性能信息入库
                        }
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}